home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1995 Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * As a special exception, the Free Software Foundation gives permission
- * for additional uses of the text contained in its release of GUILE.
- *
- * The exception is that, if you link the GUILE library with other files
- * to produce an executable, this does not by itself cause the
- * resulting executable to be covered by the GNU General Public License.
- * Your use of that executable is in no way restricted on account of
- * linking the GUILE library code into it.
- *
- * This exception does not however invalidate any other reasons why
- * the executable file might be covered by the GNU General Public License.
- *
- * This exception applies only to the code released by the
- * Free Software Foundation under the name GUILE. If you copy
- * code from other Free Software Foundation releases into a copy of
- * GUILE, as the General Public License permits, the exception does
- * not apply to the code that you add in this way. To avoid misleading
- * anyone as to the status of such modified files, you must delete
- * this exception notice from them.
- *
- * If you write modifications of your own for GUILE, it is your choice
- * whether to permit this exception to apply to your modifications.
- * If you do not wish that, delete this exception notice.
- */
-
-
- #include <stdio.h>
- #include "_scm.h"
-
-
-
-
- /* scm_ptobs scm_numptob
- * implement a dynamicly resized array of ptob records.
- * Indexes into this table are used when generating type
- * tags for smobjects (if you know a tag you can get an index and conversely).
- */
- scm_ptobfuns *scm_ptobs;
- sizet scm_numptob;
-
- long
- scm_newptob (ptob)
- scm_ptobfuns *ptob;
- {
- char *tmp;
- if (255 <= scm_numptob)
- goto ptoberr;
- DEFER_INTS;
- SYSCALL (tmp = (char *) realloc ((char *) scm_ptobs, (1 + scm_numptob) * sizeof (scm_ptobfuns)));
- if (tmp)
- {
- scm_ptobs = (scm_ptobfuns *) tmp;
- scm_ptobs[scm_numptob].mark = ptob->mark;
- scm_ptobs[scm_numptob].free = ptob->free;
- scm_ptobs[scm_numptob].print = ptob->print;
- scm_ptobs[scm_numptob].equalp = ptob->equalp;
- scm_ptobs[scm_numptob].fputc = ptob->fputc;
- scm_ptobs[scm_numptob].fputs = ptob->fputs;
- scm_ptobs[scm_numptob].fwrite = ptob->fwrite;
- scm_ptobs[scm_numptob].fflush = ptob->fflush;
- scm_ptobs[scm_numptob].fgetc = ptob->fgetc;
- scm_ptobs[scm_numptob].fclose = ptob->fclose;
- scm_numptob++;
- }
- ALLOW_INTS;
- if (!tmp)
- ptoberr:scm_wta (MAKINUM ((long) scm_numptob), (char *) NALLOC, "newptob");
- return tc7_port + (scm_numptob - 1) * 256;
- }
-
-
-
-
- /* {Ports - in general}
- *
- */
-
- /* Array of open ports, required for reliable MOVE->FDES etc. */
- struct scm_port_table *scm_port_table;
-
- int scm_port_table_size = 0; /* Number of ports in scm_port_table. */
- int scm_port_table_room = 20; /* Size of the array. */
-
- /* Add a port to the table. Call with DEFER_INTS active. */
- #ifdef __STDC__
- void
- scm_add_to_port_table (SCM port)
- #else
- void
- scm_add_to_port_table (port)
- SCM port;
- #endif
- {
- if (scm_port_table_size == scm_port_table_room) {
- scm_port_table = (struct scm_port_table *)
- scm_must_realloc ((char *) scm_port_table,
- (long) (sizeof (struct scm_port_table)
- * scm_port_table_room),
- (long) (sizeof (struct scm_port_table)
- * scm_port_table_room * 2),
- "port list");
- scm_port_table_room *= 2;
- }
- scm_port_table[scm_port_table_size].port = port;
- scm_port_table[scm_port_table_size].revealed = 0;
- scm_port_table_size++;
- }
-
- /* Remove a port from the table. Call with DEFER_INTS active. */
- #ifdef __STDC__
- void
- scm_remove_from_port_table (SCM port)
- #else
- void
- scm_remove_from_port_table (port)
- SCM port;
- #endif
- {
- int i = 0;
- while (scm_port_table[i].port != port)
- {
- i++;
- /* Error if not found: too violent? May occur in GC. */
- if (i >= scm_port_table_size)
- scm_wta (port, "Port not in table", "scm_remove_from_port_table");
- }
- scm_port_table[i].port = scm_port_table[scm_port_table_size - 1].port;
- scm_port_table[i].revealed
- = scm_port_table[scm_port_table_size - 1].revealed;
- scm_port_table_size--;
- }
-
- #ifdef DEBUG
- /* Undocumented functions for debugging. */
- /* Return the number of ports in the table. */
- static char s_pt_size[] = "pt-size";
- #ifdef __STDC__
- SCM
- scm_pt_size (void)
- #else
- SCM
- scm_pt_size ()
- #endif
- {
- return MAKINUM (scm_port_table_size);
- }
-
- /* Return the ith member of the port table. */
- static char s_pt_member[] = "pt-member";
- #ifdef __STDC__
- SCM
- scm_pt_member (SCM member)
- #else
- SCM
- scm_pt_member (member)
- SCM member;
- #endif
- {
- int i;
- ASSERT (INUMP (member), member, ARG1, s_pt_member);
- i = INUM (member);
- if (i < 0 || i >= scm_port_table_size)
- return BOOL_F;
- else
- return scm_port_table[i].port;
- }
- #endif
-
- /* Close all ports except those listed. Useful when creating new
- * processes.
- */
-
- PROC (s_close_all_ports_except, "close-all-ports-except", 0, 0, 1, scm_close_all_ports_except);
- #ifdef __STDC__
- SCM
- scm_close_all_ports_except (SCM ports)
- #else
- SCM
- scm_close_all_ports_except (ports)
- SCM ports;
- #endif
- {
- int i = 0;
- ASSERT (NIMP (ports) && CONSP (ports), ports, ARG1, s_close_all_ports_except);
- DEFER_INTS;
- while (i < scm_port_table_size)
- {
- SCM thisport = scm_port_table[i].port;
- int found = 0;
- SCM ports_ptr = ports;
-
- while (NNULLP (ports_ptr))
- {
- SCM port = CAR (ports_ptr);
- if (i == 0)
- ASSERT (NIMP (port) && OPPORTP (port), port, ARG1, s_close_all_ports_except);
- if (port == thisport)
- found = 1;
- ports_ptr = CDR (ports_ptr);
- }
- if (found)
- i++;
- else
- /* i is not to be incremented here. */
- scm_close_port (thisport);
- }
- ALLOW_INTS;
- return UNSPECIFIED;
- }
-
- /* Find a port in the table and return its revealed count. Return -1
- * if the port isn't in the table (should not happen). Also used by
- * the garbage collector.
- */
- #ifdef __STDC__
- int
- scm_revealed_count (SCM port)
- #else
- int
- scm_revealed_count (port)
- SCM port;
- #endif
- {
- int i;
-
- for (i = 0; i < scm_port_table_size; i++)
- {
- if (scm_port_table[i].port == port)
- return scm_port_table[i].revealed;
- }
- return -1;
- }
-
-
- PROC (s_port_to_descriptor, "port->descriptor", 1, 0, 0, scm_port_to_descriptor);
- #ifdef __STDC__
- SCM
- scm_port_to_descriptor (SCM port)
- #else
- SCM
- scm_port_to_descriptor (port)
- SCM port;
- #endif
- {
- int it;
- ASSERT (NIMP (port) && FPORTP (port), port, ARG1, s_port_to_descriptor);
- DEFER_INTS;
- it = fileno (STREAM (port));
- ALLOW_INTS;
- return MAKINUM (it);
- }
-
- /* Return the revealed count for a port. */
-
- PROC (s_port_revealed, "port-revealed", 1, 0, 0, scm_port_revealed);
- #ifdef __STDC__
- SCM
- scm_port_revealed (SCM port)
- #else
- SCM
- scm_port_revealed (port)
- SCM port;
- #endif
- {
- int result;
-
- ASSERT (NIMP (port) && PORTP (port), port, ARG1, s_port_revealed);
-
- if ((result = scm_revealed_count (port)) == -1)
- return BOOL_F;
- else
- return MAKINUM (result);
- }
-
- /* Set the revealed count for a port. */
- PROC (s_set_port_revealed_x, "set-port-revealed!", 2, 0, 0, scm_set_port_revealed_x);
- #ifdef __STDC__
- SCM
- scm_set_port_revealed_x (SCM port, SCM rcount)
- #else
- SCM
- scm_set_port_revealed_x (port, rcount)
- SCM port;
- SCM rcount;
- #endif
- {
- int i;
-
- ASSERT (NIMP (port) && PORTP (port), port, ARG1, s_set_port_revealed_x);
- ASSERT (INUMP (rcount), rcount, ARG2, s_set_port_revealed_x);
- DEFER_INTS;
- for (i = 0; i < scm_port_table_size; i++)
- {
- if (scm_port_table[i].port == port) {
- scm_port_table[i].revealed = INUM (rcount);
- return BOOL_T;
- }
- }
- ALLOW_INTS;
- return BOOL_F;
- }
-
- /* FIXME */
- #ifdef __STDC__
- void
- scm_setfileno (FILE *fs, int fd)
- #else
- void
- scm_setfileno (fs, fd)
- FILE *fs;
- int fd;
- #endif
- {
- #ifdef FILE_FD_FIELD
- fs->FILE_FD_FIELD = fd;
- #else
- Configure could not guess the name of the correct field in a FILE *.
- This function needs to be ported to your system.
- It should change the descriptor refered to by a stdio stream, and nothing
- else.
- #endif
- }
-
- /* Move ports with the specified file descriptor to new descriptors,
- * reseting the revealed count to 0.
- * Should be called with DEFER_INTS active.
- */
- #ifdef __STDC__
- void
- scm_evict_ports (int fd)
- #else
- void
- scm_evict_ports (fd)
- int fd;
- #endif
- {
- int i;
-
- for (i = 0; i < scm_port_table_size; i++)
- {
- if (FPORTP (scm_port_table[i].port)
- && fileno (STREAM (scm_port_table[i].port)) == fd)
- {
- scm_setfileno (STREAM (scm_port_table[i].port), dup (fd));
- scm_set_port_revealed_x (scm_port_table[i].port, MAKINUM (0));
- }
- }
- }
-
- /* Return a list of ports using a given file descriptor. */
- PROC (s_fdes_to_ports, "fdes->ports", 1, 0, 0, scm_fdes_to_ports);
- #ifdef __STDC__
- SCM
- scm_fdes_to_ports (SCM fd)
- #else
- SCM
- scm_fdes_to_ports (fd)
- SCM fd;
- #endif
- {
- SCM result = EOL;
- int int_fd;
- int i;
-
- ASSERT (INUMP (fd), fd, ARG1, s_fdes_to_ports);
- int_fd = INUM (fd);
-
- DEFER_INTS;
- for (i = 0; i < scm_port_table_size; i++)
- {
- if (FPORTP (scm_port_table[i].port)
- && fileno (STREAM (scm_port_table[i].port)) == int_fd)
- result = scm_cons (scm_port_table[i].port, result);
- }
- ALLOW_INTS;
- return result;
- }
-
-
- /* scm_close_port
- * Call the close operation on a port object.
- */
- PROC (s_close_port, "close-port", 1, 0, 0, scm_close_port);
- #ifdef __STDC__
- SCM
- scm_close_port (SCM port)
- #else
- SCM
- scm_close_port (port)
- SCM port;
- #endif
- {
- sizet i;
- ASSERT (NIMP (port) && PORTP (port), port, ARG1, s_close_port);
- if (CLOSEDP (port))
- return UNSPECIFIED;
- i = PTOBNUM (port);
- DEFER_INTS;
- if (scm_ptobs[i].fclose)
- SYSCALL ((scm_ptobs[i].fclose) (STREAM (port)));
- scm_remove_from_port_table (port);
- CAR (port) &= ~OPN;
- ALLOW_INTS;
- return UNSPECIFIED;
- }
-
-
- PROC (s_input_port_p, "input-port?", 1, 0, 0, scm_input_port_p);
- #ifdef __STDC__
- SCM
- scm_input_port_p (SCM x)
- #else
- SCM
- scm_input_port_p (x)
- SCM x;
- #endif
- {
- if (IMP (x))
- return BOOL_F;
- return INPORTP (x) ? BOOL_T : BOOL_F;
- }
-
- PROC (s_output_port_p, "output-port?", 1, 0, 0, scm_output_port_p);
- #ifdef __STDC__
- SCM
- scm_output_port_p (SCM x)
- #else
- SCM
- scm_output_port_p (x)
- SCM x;
- #endif
- {
- if (IMP (x))
- return BOOL_F;
- return OUTPORTP (x) ? BOOL_T : BOOL_F;
- }
-
-
- #ifndef ttyname
- extern char * ttyname();
- #endif
-
- #ifdef __STDC__
- void
- scm_prinport (SCM exp, SCM port, char *type)
- #else
- void
- scm_prinport (exp, port, type)
- SCM exp;
- SCM port;
- char *type;
- #endif
- {
- scm_puts ("#<", port);
- if (CLOSEDP (exp))
- scm_puts ("closed-", port);
- else
- {
- if (RDNG & CAR (exp))
- scm_puts ("input-", port);
- if (WRTNG & CAR (exp))
- scm_puts ("output-", port);
- }
- scm_puts (type, port);
- scm_putc (' ', port);
- #ifndef MSDOS
- #ifndef __EMX__
- #ifndef _DCC
- #ifndef AMIGA
- #ifndef THINK_C
- if (OPENP (exp) && tc16_fport == TYP16 (exp) && isatty (fileno (STREAM (exp))))
- scm_puts (ttyname (fileno (STREAM (exp))), port);
- else
- #endif
- #endif
- #endif
- #endif
- #endif
- if (OPFPORTP (exp))
- scm_intprint ((long) fileno (STREAM (exp)), 10, port);
- else
- scm_intprint (CDR (exp), 16, port);
- scm_putc ('>', port);
- }
-
- #ifdef __STDC__
- void
- scm_ports_prehistory (void)
- #else
- void
- scm_ports_prehistory ()
- #endif
- {
- scm_numptob = 0;
- scm_ptobs = (scm_ptobfuns *) malloc (4 * sizeof (scm_ptobfuns));
-
- /* WARNING: These scm_newptob calls must be done in this order */
- /* tc16_fport = */ scm_newptob (&scm_fptob);
- /* tc16_pipe = */ scm_newptob (&scm_pipob);
- /* tc16_strport = */ scm_newptob (&scm_stptob);
- /* tc16_sfport = */ scm_newptob (&scm_sfptob);
- }
-
-
- #ifdef __STDC__
- void
- scm_init_ports (void)
- #else
- void
- scm_init_ports ()
- #endif
- {
- #include "ports.x"
- }
-
-